home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / CBlibrary / c / InputFocus < prev    next >
Encoding:
Text File  |  2003-10-16  |  5.4 KB  |  157 lines

  1. /*
  2.  * CBLibrary - InputFocus
  3.  * Copyright (C) 2003  Chris Bazley
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19.  
  20. /*
  21.  * Code to record the caret position prior to opening transient
  22.  * dboxes (e.g. on Window_AboutToBeShown event), and restore it when
  23.  * the menu tree is closed (if no other window has taken it).
  24.  * It can be used to work around a bug in the Toolbox: When closed,
  25.  * transient windows with default input focus in the window background
  26.  * do not restore the caret to the window from which they borrowed it.
  27.  */
  28.  
  29. #ifndef NDEBUG
  30. #include <stdio.h>
  31. #include "kernel.h"
  32. #endif
  33.  
  34. #include "wimp.h"
  35. #include "wimplib.h"
  36. #include "event.h"
  37. #include "window.h"
  38. #include "menu.h"
  39. #include "DCS.h"
  40. #include "Quit.h"
  41.  
  42. #include "InputFocus.h"
  43. #include "err.h"
  44. #include "Macros.h"
  45.  
  46. /* N.B. there can be only one transient dbox open at a time */
  47. static WimpCaret caret_store;
  48. static int window_handle = -1; /* not a valid window handle */
  49.  
  50. /* ----------------------------------------------------------------------- */
  51. /*                       Function prototypes                               */
  52.  
  53. static WimpMessageHandler _InputFocus_menusdeleted;
  54.  
  55. /* ----------------------------------------------------------------------- */
  56. /*                         Public functions                                */
  57.  
  58. _kernel_oserror *InputFocus_initialise(void)
  59. {
  60.   return event_register_message_handler(Wimp_MMenusDeleted, _InputFocus_menusdeleted, NULL);
  61. }
  62.  
  63. /* ----------------------------------------------------------------------- */
  64.  
  65. int InputFocus_recordcaretpos(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  66. {
  67.   /* Can only handle those classes for which we know how to get window
  68.   handle. Also, the AboutToBeShown event blocks for these 3 have a
  69.   common structure */
  70.   NOT_USED(handle)
  71.  
  72.   ObjectId window_id;
  73.   switch(event_code) {
  74.     case DCS_AboutToBeShown:
  75.       E_RETV(dcs_get_window_id(0, id_block->self_id, &window_id), 0)
  76.       break;
  77.  
  78.     case Quit_AboutToBeShown:
  79.       E_RETV(quit_get_window_id(0, id_block->self_id, &window_id), 0)
  80.       break;
  81.  
  82.     case Window_AboutToBeShown:
  83.       window_id = id_block->self_id;
  84.       break;
  85.  
  86.     default:
  87.       return 0; 
  88.   } 
  89.  
  90.   /* Check that we are being shown transiently - otherwise we might let
  91.   ourselves in for a whole heap of trouble */
  92.   if(!FLAG_SET(event->hdr.flags, Toolbox_ShowObject_AsMenu))
  93.     return 0;
  94.  
  95.   /* Is this dbox hanging off a menu tree? */
  96.   ObjectClass parent_class = 0;
  97.   if(id_block->parent_id != NULL_ObjectId)
  98.     /* parent may have been deleted, so ignore error return */
  99.     toolbox_get_object_class(0, id_block->parent_id, &parent_class);
  100.  
  101.   if(parent_class == Menu_ObjectClass)
  102.     /* don't attempt to match window handle */
  103.     window_handle = -2; 
  104.   else
  105.     /* No - record window handle to compare against MenusDeleted message */
  106.     RE(window_get_wimp_handle(0, window_id, &window_handle))
  107.  
  108.   RE(wimp_get_caret_position(&caret_store))
  109. #ifndef NDEBUG
  110.   sprintf(string, "report recording caret pos: %d, %d, %d, %d, %d, %d prior to opening window %d (wimp handle %d)", ((WimpCaret *)handle)->window_handle, ((WimpCaret *)handle)->icon_handle, ((WimpCaret *)handle)->xoffset, ((WimpCaret *)handle)->yoffset, ((WimpCaret *)handle)->height, ((WimpCaret *)handle)->index, id_block->self_id, window_handle);
  111.   _kernel_oscli(string);
  112. #endif
  113.  
  114.   return 0; /* don't claim event */
  115. }
  116.  
  117. /* ----------------------------------------------------------------------- */
  118.  
  119. _kernel_oserror *InputFocus_restorecaret(void)
  120. {
  121.   /* Find current caret position */
  122.   WimpGetCaretPositionBlock now_pos;
  123.   THROW(wimp_get_caret_position(&now_pos))
  124. #ifndef NDEBUG
  125.   sprintf(string, "report post-close caret pos: %d, %d, %d, %d, %d, %d", now_pos.window_handle, now_pos.icon_handle, now_pos.xoffset, now_pos.yoffset, now_pos.height, now_pos.index);
  126.   _kernel_oscli(string);
  127. #endif
  128.   
  129.   /* Attempt to restore the input focus (if no window has claimed it)
  130.      Ignore any error, cos it probably means previous owner is dead */
  131.   if(now_pos.window_handle == -1)
  132.     wimp_set_caret_position(caret_store.window_handle, caret_store.icon_handle, caret_store.xoffset, caret_store.yoffset, caret_store.height, caret_store.index);
  133.   return NULL;
  134. }
  135.  
  136. /* ----------------------------------------------------------------------- */
  137. /*                         Private functions                               */
  138.  
  139. int _InputFocus_menusdeleted(WimpMessage *message, void *handle)
  140. {
  141.   NOT_USED(handle)
  142. #ifndef NDEBUG
  143.   char string[255];
  144.   sprintf(string, "report Message_MenusDeleted received for %d", message->words[0]);
  145.   _kernel_oscli(string);
  146. #endif
  147.  
  148.   if(message->data.words[0] == window_handle || window_handle == -2) {
  149.     /* Our dbox has just closed or we don't care about handle */
  150.     window_handle = -1;
  151.  
  152.     RE(InputFocus_restorecaret());
  153.   }
  154.  
  155.   return 0; /* don't claim event */
  156. }
  157.